💡 本篇主題與重點字:**super**
昨天提到 JavaScript 是一門基於原型繼承的語言,不同於傳統物件導向語言的類別繼承,透過建構函式和原型鏈來實現繼承。

這種寫法雖然功能完整,但語法較為冗長且容易出錯。ES6 引入了 class 語法糖,讓繼承變得更加直觀,而 super 關鍵字正是這套語法的核心機制之一!
語法糖: 電腦語言中添加的某種語法,這種語法對語言的功能沒有影響,但是更方便程式設計師使用。 —— 維基
當我們在 JavaScript 的 class 語法中使用 super 時,實際上是對父類別(superclass)的一種訪問方式,底層仍然依賴原型鏈與函式綁定機制。讓我們看看上面的程式碼在底層是如何運作的:
Class Animal 的實際轉換
Class Animal 實際上變成了一個 constructor,然後再把 speak 方法加到 Animal.prototype 上。
Class Dog 的實際轉換
Class Dog 也先變成一個 constructor,然後如昨天的步驟建立原型鏈繼承關係,再把新的方法 bark 添加到 Dog.prototype。
這樣的轉換讓我們理解到:
Dog.prototype.__proto__ === Animal.prototype 為真Dog.__proto__ === Animal(用於靜態方法的繼承)在 ES6 語法中,super(name) 看起來像是直接呼叫父類的建構函式,但實際的工作原理其實誠如昨天所說的 call。當你在子類的 constructor 中使用 super() 時,JavaScript 引擎會:
this 的綁定設定為正在創建的新實例this 傳入這個過程本質上就是 Animal.call(this, name) 的等價物。
所有的方法調用,因為語法糖畢竟不改變邏輯,所以最終實際上的底層實作都會回到昨天的原理:當在一個方法內使用 super.method() 時,JavaScript 引擎會先找出這個方法的定義位置的原型,然後沿著原型鏈向上尋找該方法並執行(或是直到找不到)。
1. 在 constructor 中呼叫父類別的建構函數
super(name) 呼叫的是 Animal 的建構函式,等同於 Animal.call(this, name)
super(),否則會出現錯誤,因為 this 還沒被初始化2. 呼叫父類別的實例方法

這樣會得到
Fido makes a noise.
Fido barks.
需要特別注意的是,super.method() 中的 this 仍然指向當前實例,而不是父類別,我們可以回顧前幾天的 this 是誰,因為 this 是動態傳入 super() 底層機制的 .call(this) ,因此指向的對象是子類別。

| 比較項目 | ES5 傳統原型繼承 | ES6 class 語法 |
|---|---|---|
| 建構函式定義 | 使用 function |
使用 class |
| 屬性繼承 | Parent.call(this) |
super() |
| 方法繼承 | Object.create() 設定原型鏈 |
extends 自動建立 |
| 原型鏈設定 | 手動設定 prototype |
語法糖,自動處理 |
| 可讀性 | 較複雜,容易出錯 | 理解上會更貼近 OOP |
| 實質本質 | 基於 prototype chain | 基於 prototype chain |
Dog.prototype.constructor = Dog 這步驟自動完成extends 讓繼承關係一目了然一般來說,現在已經不會看到有 ES5 的寫法了,但為了更好地掌握 JS 本質以避免一些奇怪的 bug,知道這些語法糖底下的基礎邏輯與如何解析運行,還是蠻重要的!!